// Copyright 2013 Petar Maymounkov
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// 4tc is the circuit template compiler
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"text/template"
	"io"
	"io/ioutil"
	"os"
)

func usage() {
	println(fmt.Sprintf("Usage: %s libGlob pageFile [outFile]", os.Args[0]))
	os.Exit(1)
}

func main() {
	flag.Parse()
	if flag.NArg() < 2 {
		usage()
	}

	// Load template library
	t := template.New("")
	if _, err := t.ParseGlob(flag.Arg(0)); err != nil {
		println(err.Error())
		os.Exit(1)
	}

	// Parse page file
	meta, err := loadPage(t, flag.Arg(1))
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}

	// Execute the page template
	var w bytes.Buffer
	if err := t.Execute(&w, meta); err != nil {
		println(err.Error())
		os.Exit(1)
	}

	if flag.NArg() == 3 {
		if err = ioutil.WriteFile(flag.Arg(2), w.Bytes(), 0666); err != nil {
			println(err.Error())
			os.Exit(1)
		}
	} else {
		io.Copy(os.Stdout, &w)
	}
}

func loadPage(t *template.Template, name string) (map[string]interface{}, error) {
	art, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, err
	}

	// Parse page meta data
	meta := make(map[string]interface{})
	if bytes.HasPrefix(art, []byte("{\n")) {
		i := bytes.Index(art, []byte("\n}\n"))
		if i < 0 {
			panic("cannot find end of json metadata")
		}
		hdr, rest := art[:i+3], art[i+3:]
		if err := json.Unmarshal(hdr, &meta); err != nil {
			panic(fmt.Sprintf("loading %s: %s", name, err))
		}
		art = rest
	}

	// Add page template
	if _, err = t.Parse(string(art)); err != nil {
		return nil, err
	}

	return meta, nil
}
